<template>
  <div>
    <!-- select框绑定的值是selectVal，也就是treeData里的value -->
    <el-select v-model="props.modelValue"
               placeholder="请选择..."
               clearable
               ref="selectRef"
               class="ld-select">
      <!-- 设置一个input框用作模糊搜索选项功能 -->
      <el-input class="ld-select-search"
                placeholder="此处键入'关键词'搜索查询"
                prefix-icon="elementSearch"
                v-model="treeFilter"
                clearable/>
      <!-- 设置一个隐藏的下拉选项，选项显示的是汉字label，值是value -->
      <!-- 如果不设置一个下拉选项，下面的树形组件将无法正常使用 -->
      <el-option hidden key="id" :value="props.modelValue" :label="selectName"/>
      <!-- 设置树形控件 -->
      <el-tree :data="props.treeData"
               :props="props.defaultProps"
               @node-click="handleNodeClick"
               :expand-on-click-node="false"
               :check-on-click-node="true"
               ref="treeRef"
               node-key="id"
               :default-expand-all="false"
               :filter-node-method="filterNode">
        <!-- @node-click：树形控件选项点击事件 -->
        <!-- :expand-on-click-node：使树形控件只有点箭头图标的时候才会展开或者收缩节点，为false则点文字直接选中该项 -->
        <!-- :check-on-click-node：是否在点击节点的时候选中节点，当选项为复选框时有用，这个属性可以删除 -->
        <!-- :default-expand-all：默认展开所有节点 -->
        <!-- :filter-node-method：实现搜索功能的筛选方法 -->
        <template #default="{ data }">
          <!-- 选项用插槽来显示，匹配搜索功能，并方便增加tag标签需求 -->
          <span>{{ data.label }}</span>
          <el-tag size="mini"
                  style="margin: 0 10px"
                  v-show="filterorgType(data.tag)">
            {{ filterorgType(data.tag) }}
          </el-tag>
        </template>
      </el-tree>
    </el-select>
  </div>
</template>

<script lang="ts" setup>
import {defineProps, ref, watch,getCurrentInstance} from 'vue';

const { proxy } = getCurrentInstance() as any;
// 定义响应式数据
const selectName = ref(''); // select框显示的name
const treeFilter = ref(''); // 搜索框绑定值，用作过滤

export interface Tree {
  value: string;
  label: string;
  tag?: string;
  children?: Tree[];
}

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  treeData: {
    type: Array,
    default: Array as () => Tree[]
  },
  defaultProps: {
    type: Object,
    default: () => ({
      children: "children",
      label: "label",
    })
  },
})
// 标签数组
const tagList = ref([
  {value: "wife", label: "老婆"},
  {value: "princess", label: "小公主"},
  {value: "yyds", label: "天下第一"},
]);

// 定义 ref
const selectRef = ref(null);
const treeRef = ref(null);

// 搜索过滤，监听input搜索框绑定的treeFilter
watch(treeFilter, (val) => {
  if (treeRef.value) {
    treeRef.value.filter(val);
    // 当搜索框键入值改变时，将该值作为入参执行树形控件的过滤事件filterNode
  }
});

// 结构树点击事件
const handleNodeClick = (data) => {
  proxy.$emit('update:modelValue',data.value);
  selectName.value = data.label; // input中显示值为label
  treeFilter.value = ""; // 点击后搜索框清空
  if (selectRef.value) {
    selectRef.value.blur(); // 点击后关闭下拉框，因为点击树形控件后select不会自动折叠
  }
};

// 模糊查询（搜索过滤），实质为筛选出树形控件中符合输入条件的选项，过滤掉其他选项
const filterNode = (value, data) => {
  if (!value) return true;
  return data.label.indexOf(value) !== -1;
};

// 选项卡标签（可忽略，增值迭代需求）
const filterorgType = (val) => {
  const arr = tagList.value.filter((item) => {
    return item.value === val;
  });
  return arr.length ? arr[0].label : "";
};

watch(() => props.treeData, (newData, oldData) => {
  console.log('treeData 发生变化:', newData, oldData);
}, { deep: true });

</script>

<style lang="scss" scoped>
.ld-select {
  width: 100%;
}

.ld-select-search {
  width: 95%;
  margin: 10px;
}
</style>